using LiteDB;
using System;
using System.IO;
using System.Threading.Tasks;
using DidaManager.Log;

namespace LiteDb
{
    /// <summary>
    /// 完整的多数据库服务器 - 结合主数据库和设备数据库
    /// </summary>
    public class FullMultiDbServer : IDisposable
    {
        private readonly MainDbManager _mainDbManager;
        private readonly MultiDbManager _multiDbManager;

        public FullMultiDbServer(MultiDbConfiguration? config = null)
        {
            config = config ?? new MultiDbConfiguration();
            
            LogManager.Info($"正在初始化完整多数据库服务器...");
            LogManager.Info($"数据库根目录: {config.BasePath}");
            
            var mainDbPath = Path.Combine(config.BasePath, config.MainDbFileName);
            _mainDbManager = new MainDbManager(mainDbPath);
            _multiDbManager = new MultiDbManager(config);
            
            LogManager.Info($"完整多数据库服务器初始化完成");
            
            // 设置设备数据库操作回调
            _mainDbManager.OnDeviceAdded = (deviceId) =>
            {
                try
                {
                    LogManager.Info($"开始创建设备数据库: device_{deviceId}.db");
                    
                    // 在创建新设备数据库前，确保没有旧的连接
                    try
                    {
                        _multiDbManager.ForceCloseDeviceDatabase(deviceId);
                    }
                    catch (Exception ex)
                    {
                        LogManager.Debug($"清理设备 {deviceId} 旧连接时出现问题（可忽略）: {ex.Message}");
                    }
                    
                    // 创建设备数据库文件
                    var deviceServer = _multiDbManager.GetDeviceCefSharpServer(deviceId);
                    LogManager.Info($"设备数据库 device_{deviceId}.db 已创建完成");
                    return ApiResponse.Success($"设备数据库 device_{deviceId}.db 创建成功");
                }
                catch (Exception ex)
                {
                    LogManager.Error($"创建设备数据库时出错: {ex.Message}", ex);
                    return ApiResponse.Fail($"创建设备数据库失败: {ex.Message}");
                }
            };
            
            _mainDbManager.OnDeviceDeleted = (deviceId, groupId) =>
            {
                try
                {
                    // 删除设备数据库文件
                    var fileDeleted = _multiDbManager.DeleteDeviceDatabase(deviceId, groupId);
                    var message = $"设备数据库 device_{deviceId}.db {'(' + (fileDeleted ? "已删除" : "未找到") + ')'}";
                    LogManager.Info(message);
                    return ApiResponse.Success(message);
                }
                catch (Exception ex)
                {
                    LogManager.Error($"删除设备数据库时出错: {ex.Message}", ex);
                    return ApiResponse.Fail($"删除设备数据库失败: {ex.Message}");
                }
            };
            
            // 设置分组数据库操作回调
            _mainDbManager.OnGroupDeleted = (groupId) =>
            {
                try
                {
                    LogManager.Info($"开始删除分组数据库文件夹: group_{groupId}");
                    var result = _multiDbManager.DeleteGroupDatabases(groupId);
                    if (result is ApiResponse apiResponse && apiResponse.IsSuccess)
                    {
                        LogManager.Info($"分组数据库文件夹 group_{groupId} 删除成功");
                        return ApiResponse.Success("分组数据库文件夹删除成功");
                    }
                    else
                    {
                        LogManager.Warn($"分组数据库文件夹 group_{groupId} 删除失败或不存在");
                        return ApiResponse.Fail($"分组数据库文件夹 group_{groupId} 删除失败");
                    }
                }
                catch (Exception ex)
                {
                    LogManager.Error($"删除分组数据库文件夹时出错: {ex.Message}", ex);
                    return ApiResponse.Fail($"删除分组数据库文件夹失败: {ex.Message}");
                }
            };

            _mainDbManager.OnExportGroupDevice = (param,configJson) =>
            {
                try
                {
                    var result = _multiDbManager.ExportGroupDevice(param, configJson);
                    return result;// 返回的是ApiResponse
                }
                catch (Exception ex)
                {
                    LogManager.Error($"导出分组设备时出错: {ex.Message}", ex);
                    return ApiResponse.Fail($"导出分组设备失败: {ex.Message}");
                }
            };

            _mainDbManager.OnImportGroupDevice = (param, deviceId) =>
            {
                try
                {   
                    var result = _multiDbManager.ImportGroupDevice(param, deviceId);
                    
                    // 如果导入成功，重新创建设备数据库连接
                    if (result is ApiResponse apiResponse && apiResponse.IsSuccess)
                    {
                        try
                        {
                            LogManager.Info($"导入完成，重新创建设备 {deviceId} 的数据库连接");
                            // 重新创建设备数据库连接
                            var deviceServer = _multiDbManager.GetDeviceCefSharpServer(deviceId);
                            LogManager.Info($"设备 {deviceId} 的数据库连接已重新建立");
                            return ApiResponse.Success(new { 
                                importResult = result,
                                connectionResult = "数据库连接已重新建立"
                            }, "导入成功并重新建立连接");
                        }
                        catch (Exception ex)
                        {
                            LogManager.Error($"重新创建设备数据库连接时出错: {ex.Message}", ex);
                            return ApiResponse.Success(new { 
                                importResult = result,
                                connectionError = ex.Message
                            }, "导入成功但重新建立连接时出错");
                        }
                    }
                    
                    return result;
                }
                catch (Exception ex)
                {
                    LogManager.Error($"导入分组设备时出错: {ex.Message}", ex);
                    return ApiResponse.Fail($"导入分组设备失败: {ex.Message}");
                }
            };
        }

        /// <summary>
        /// 调用主数据库方法
        /// </summary>
        public Task<object?> CallMainDbMethod(string methodName, object param)
        {
            var type = _mainDbManager.GetType();
            var method = type.GetMethod(methodName, new[] { typeof(object) });
            if (method == null)
            {
                return Task.FromResult<object?>(ApiResponse.NotFound());
            }
            var result = method.Invoke(_mainDbManager, new[] { param });
            return Task.FromResult<object?>(result);
        }

        /// <summary>
        /// 调用设备数据库方法
        /// </summary>
        public Task<object?> CallMultiDbMethod(string methodName, object param, object deviceId)
        {
            // 把deviceId转为int
            int deviceIdInt = Convert.ToInt32(deviceId);
            CefSharpServer cefSharpServer = GetDeviceCefSharpServer(deviceIdInt);
            return cefSharpServer.CallMethod(methodName, param);
        }

        /// <summary>
        /// 调用方法 - 优先尝试主数据库，再尝试设备数据库方法
        /// </summary>
        public async Task<object?> callDbMethod(string methodName, object param, object? deviceId = null)
        {
            try
            {
                // 优先尝试主数据库方法
                var result = await CallMainDbMethod(methodName, param);
                var apiResponse = result as ApiResponse;
                if (apiResponse == null || apiResponse.IsMethodNotFound)
                {
                    if (deviceId != null)
                    {
                        // 尝试设备数据库方法
                        return await CallMultiDbMethod(methodName, param, deviceId);
                    }
                }
                return result;
            }
            catch (Exception ex)
            {
                return ApiResponse.Fail($"调用方法失败: {ex.Message}");
            }
        }

        /// <summary>
        /// 获取设备CefSharpServer
        /// </summary>
        public CefSharpServer GetDeviceCefSharpServer(int deviceId)
        {
            return _multiDbManager.GetDeviceCefSharpServer(deviceId);
        }

        /// <summary>
        /// 强制关闭设备数据库连接（用于文件操作前释放资源）
        /// </summary>
        public void ForceCloseDeviceDatabase(int deviceId)
        {
            _multiDbManager.ForceCloseDeviceDatabase(deviceId);
        }

        /// <summary>
        /// 强制覆盖设备数据库文件
        /// </summary>
        /// <param name="deviceId">设备ID</param>
        /// <param name="sourcePath">源文件路径</param>
        /// <returns>操作结果</returns>
        public object ForceOverwriteDeviceDatabase(int deviceId, string sourcePath)
        {
            try
            {
                if (string.IsNullOrEmpty(sourcePath) || !File.Exists(sourcePath))
                {
                    return ApiResponse.Fail("源文件不存在");
                }

                LogManager.Info($"开始强制覆盖设备 {deviceId} 的数据库文件");

                // 1. 强制关闭数据库连接
                ForceCloseDeviceDatabase(deviceId);

                // 2. 获取目标文件路径
                var groupId = _multiDbManager.GetGroupIdByDeviceId(deviceId);
                var targetPath = _multiDbManager.GetDeviceDatabasePath(deviceId, groupId);

                // 3. 使用安全文件复制
                bool copySuccess = _multiDbManager.SafeFileCopy(sourcePath, targetPath);

                if (!copySuccess)
                {
                    return ApiResponse.Fail("文件复制失败，文件可能正在被使用");
                }

                // 4. 重新创建数据库连接
                try
                {
                    var deviceServer = GetDeviceCefSharpServer(deviceId);
                    LogManager.Info($"设备 {deviceId} 的数据库文件已成功覆盖并重新连接");
                    return ApiResponse.Success("数据库文件强制覆盖成功");
                }
                catch (Exception ex)
                {
                    LogManager.Error($"重新创建数据库连接时出错: {ex.Message}", ex);
                    return ApiResponse.Fail($"文件复制成功但重新连接失败: {ex.Message}");
                }
            }
            catch (Exception ex)
            {
                LogManager.Error($"强制覆盖设备数据库文件时出错: {ex.Message}", ex);
                return ApiResponse.Fail($"强制覆盖失败: {ex.Message}");
            }
        }

        public void Dispose()
        {
            _mainDbManager?.Dispose();
            _multiDbManager?.Dispose();
        }
    }
}

